﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using Applib.Win32NativeMethods;


namespace Applib.Images
{
    public class ScreenCaptureUtil
    {
        public static void RunCapture(Rectangle hightlightArea, string desc, string fullFileName)
        {
            Rectangle screenRect = new Rectangle(new Point(0, 0),
                new Size(
                    User32NativeMethod.GetSystemMetrics(User32NativeMethod.SM_CXFULLSCREEN),
                    User32NativeMethod.GetSystemMetrics(User32NativeMethod.SM_CYFULLSCREEN)
                        )
                    );

            RectangleF textArea = new RectangleF(0, 0, 500, 200);
            Action caculateTextQuadrant = () =>
            {
                POINT screenCenter = new POINT() { X = screenRect.Right / 2, Y = screenRect.Bottom / 2 };
                PointF[] availableTextPositions = new PointF[2]
                        {
                            new Point(screenRect.Right-500,0),                           // top right
                            new Point(screenRect.Right - 500, screenRect.Bottom - 200)   // bottom right
                        };

                //the highlight and text are both in 4th quadrant.
                if (hightlightArea.X > screenCenter.X && hightlightArea.Y > screenCenter.Y)
                {
                    textArea.Location = availableTextPositions[0];
                }
                else
                {
                    textArea.Location = availableTextPositions[1];
                }

            };


            IntPtr desktop = User32NativeMethod.GetDesktopWindow();
            using (Bitmap printscreen = Capture(desktop))
            {

                caculateTextQuadrant();
                using (Graphics graphics = Graphics.FromImage(printscreen as Image))
                {
                    graphics.CompositingQuality = CompositingQuality.HighQuality;

                    GraphicsPath path = new GraphicsPath();
                    path.AddLines(new Point[4]
                    {
                        new Point( hightlightArea.X, hightlightArea.Y),
                        new Point( hightlightArea.X+hightlightArea.Width, hightlightArea.Y),
                        new Point( hightlightArea.X+hightlightArea.Width, hightlightArea.Y+hightlightArea.Height),
                        new Point( hightlightArea.X, hightlightArea.Y+hightlightArea.Height)
                    });
                    path.CloseFigure();
                    SolidBrush borderbrush = new SolidBrush(Color.Red);
                    Pen pen = new Pen(borderbrush, 2);
                    graphics.DrawPath(pen, path);

                    SolidBrush highLightBbrush = new SolidBrush(Color.FromArgb(150, 255, 255, 0));
                    graphics.FillRectangle(highLightBbrush, textArea);



                    SolidBrush txtbrush = new SolidBrush(Color.Black);
                    graphics.DrawString(desc, new Font("Verdana", 10, FontStyle.Regular), txtbrush, textArea);


                    highLightBbrush.Dispose();
                    borderbrush.Dispose();
                    txtbrush.Dispose();
                    graphics.Save();
                }

                printscreen.Save(fullFileName, ImageFormat.Jpeg);
                printscreen.Dispose();
                GC.Collect();
            }
        }

        public static Bitmap Capture(IntPtr tarWindow)
        {
            Size bmpSize = new Size(
                User32NativeMethod.GetSystemMetrics(User32NativeMethod.SM_CXFULLSCREEN),
                User32NativeMethod.GetSystemMetrics(User32NativeMethod.SM_CYFULLSCREEN));
            int mouseX = 0, mouseY = 0;

            Func<IntPtr, Bitmap> CreateBmpFileHandle = (par) =>
            {
                IntPtr tarDc = User32NativeMethod.GetDC(par);
                IntPtr tarMemDc = Gdi32NativeMethod.CreateCompatibleDC(tarDc);
                IntPtr tarBitmap = Gdi32NativeMethod.CreateCompatibleBitmap(tarDc, bmpSize.Width, bmpSize.Height);

                if (tarBitmap != IntPtr.Zero)
                {
                    IntPtr hGdiObj = Gdi32NativeMethod.SelectObject(tarMemDc, tarBitmap);
                    Gdi32NativeMethod.BitBlt(tarMemDc, 0, 0, bmpSize.Width, bmpSize.Height, tarDc, 0, 0, User32NativeMethod.SRC_COPY);

                    Gdi32NativeMethod.SelectObject(tarMemDc, hGdiObj);

                    Gdi32NativeMethod.DeleteDC(tarDc);
                    User32NativeMethod.ReleaseDC(par, tarDc);

                    Gdi32NativeMethod.DeleteDC(tarMemDc);
                    User32NativeMethod.ReleaseDC(par, tarMemDc);

                    Bitmap bmp = System.Drawing.Image.FromHbitmap(tarBitmap);
                    Gdi32NativeMethod.DeleteObject(tarBitmap);
                    return bmp;
                }
                return null;
            };


            Func<IntPtr, Bitmap> CreateCursorFromHandle = (par) =>
            {
                Bitmap iconBmp = null;
                IntPtr hicon = IntPtr.Zero;
                CURSOR cursorInfo = new CURSOR();

                cursorInfo.cbSize = Marshal.SizeOf(cursorInfo);
                if (User32NativeMethod.GetCursorInfo(out cursorInfo))
                {
                    hicon = User32NativeMethod.CopyIcon(cursorInfo.hCursor);

                    mouseX = cursorInfo.ptScreenPos.X;
                    mouseY = cursorInfo.ptScreenPos.Y;

                    if (hicon != IntPtr.Zero)
                    {
                        Icon ic = Icon.FromHandle(hicon);
                        iconBmp = ic.ToBitmap();
                        //some icons cannot use this ToBitmap() actually. 
                        //if we need fix this we should use g.DrawIcon() something.
                    }
                    //mem leak here. if this deletion doesn't work well we should use DestroyIcon() instead
                    Gdi32NativeMethod.DeleteObject(hicon);
                }


                return iconBmp;
            };


            Bitmap windowBmp = CreateBmpFileHandle(tarWindow);
            Bitmap cursorBmp = null; //CreateCursorFromHandle(IntPtr.Zero);  will not draw cursor, it will cover some tooltip text. 
            //combine window and cursor bitmaps
            if (cursorBmp != null && windowBmp != null)
            {
                using (Graphics g = Graphics.FromImage(windowBmp as Image))
                {
                    Rectangle mouseRect = new Rectangle(mouseX, mouseY, cursorBmp.Width, cursorBmp.Height);
                    g.DrawImage(cursorBmp, mouseRect);
                    g.Flush();
                    g.Save();

                }
                cursorBmp.Dispose();
                cursorBmp = null;
            }

            return windowBmp;

        }


    }
}
